// SPDX-License-Identifier: GPL-2.0-only
#include "broiler/assembly.h"
#include "broiler/bios.h"

	.org 0
	.code16gcc

#define EFLAGS_CF	(1 << 0)

#include "macro.S"

/* If you change these macros, remember to update 'struct biosregs' */
.macro SAVE_BIOSREGS
	pushl   %fs
	pushl   %es
	pushl   %ds
	pushl   %edi
	pushl   %esi
	pushl   %ebp
	pushl   %esp
	pushl   %edx
	pushl   %ecx
	pushl   %ebx
	pushl   %eax
.endm

.macro RESTORE_BIOSREGS
	popl    %eax
	popl    %ebx
	popl    %ecx
	popl    %edx
	popl    %esp
	popl   	%ebp
	popl    %esi
	popl    %edi
	popl    %ds
	popl    %es
	popl    %fs
.endm

/*
 * fake interrupt handler, nothing can be faster ever
 */
ENTRY(bios_intfake)
	/*
	 * Set CF to indicate failure. We don't want callers to think that the
	 * interrupt handler succeeded and then treat the return values in
	 * registers as valid data.
	 */
	orl     $EFLAGS_CF, 0x4(%esp)

	IRET
ENTRY_END(bios_intfake)

/*
 * int 10 - video - service
 */
ENTRY(bios_int10)
	SAVE_BIOSREGS

	movl            %esp, %eax
	/* this is way easier than doing it in assembly */
	/* just push all the regs and jump to a C handler */
	call    int10_handler

	RESTORE_BIOSREGS

	/* Clear CF to indicate success.  */
	andl    $~EFLAGS_CF, 0x4(%esp)

	IRET
ENTRY_END(bios_int10)

ENTRY(bios_int15)
	SAVE_BIOSREGS

	movl    %esp, %eax
	call    int15_handler

	RESTORE_BIOSREGS

	IRET
ENTRY_END(bios_int15)

GLOBAL(__locals)

#include "local.S"

END(__locals)

/*
 * Add this section to ensure final binary has a non-executable stack.
 */
.section .note.GNU-stack,"",@progbits
